package cc.shacocloud.mirage.core.bind.support;

import cc.shacocloud.mirage.bean.ConfigurableBeanFactory;
import cc.shacocloud.mirage.bean.meta.BeanKey;
import cc.shacocloud.mirage.core.Condition;
import cc.shacocloud.mirage.core.ConditionContext;
import cc.shacocloud.mirage.core.bind.ConditionalOnMissingBean;
import cc.shacocloud.mirage.utils.annotation.AnnotatedElementMetadata;
import cc.shacocloud.mirage.utils.collection.ArrayUtil;
import cc.shacocloud.mirage.utils.collection.CollUtil;
import lombok.NoArgsConstructor;
import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.List;

/**
 * 基于 {@link Condition} 的 {@link ConditionalOnMissingBean} 的判断条件实现类
 *
 * @author 思追(shaco)
 * @see ConditionalOnMissingBean
 */
@NoArgsConstructor
public class OnMissingBeanCondition implements Condition {
    
    @Override
    public boolean matches(@NotNull ConditionContext context, @NotNull AnnotatedElementMetadata annotatedElementMetadata) {
        ConditionalOnMissingBean conditionalOnMissingBean = annotatedElementMetadata.getAnnotation(ConditionalOnMissingBean.class);
        assert conditionalOnMissingBean != null;
        
        final ConfigurableBeanFactory beanFactory = context.getBeanFactory();
        
        Class<?>[] type = conditionalOnMissingBean.type();
        String[] name = conditionalOnMissingBean.name();
        
        final List<BeanKey> beanKeys = new ArrayList<>();
        
        // 如果都为空
        if (ArrayUtil.isEmpty(name) && ArrayUtil.isEmpty(type)) {
            BeanKey beanKey = context.getBeanKey();
            beanKeys.add(new BeanKey(beanKey.getType(), BeanKey.ANY_QUALIFIER));
        }
        // 如果都不为空
        else if (ArrayUtil.isNotEmpty(name) && ArrayUtil.isNotEmpty(type)) {
            for (Class<?> clazz : type) {
                for (String n : name) {
                    beanKeys.add(new BeanKey(clazz, n));
                }
            }
        }
        // 如果名称不为空
        else if (ArrayUtil.isNotEmpty(name)) {
            for (String n : name) {
                beanKeys.add(new BeanKey(BeanKey.ANY_TYPE, n));
            }
        }
        // 如果类型不为空
        else if (ArrayUtil.isNotEmpty(type)) {
            for (Class<?> clazz : type) {
                beanKeys.add(new BeanKey(clazz, BeanKey.ANY_QUALIFIER));
            }
        }
        
        // 判断是否都不存在于 beanFactory 中，存在一个则忽略当前 Bean
        for (BeanKey beanKey : beanKeys) {
            List<BeanKey> matches = beanFactory.getBeanKeys(beanKey);
            if (CollUtil.isNotEmpty(matches)) return false;
        }
        
        return true;
    }
}
